package cn.wolfcode.luowowo.website.controller;

import cn.wolfcode.luowowo.article.domain.Scenic;
import cn.wolfcode.luowowo.article.service.IDestinationService;
import cn.wolfcode.luowowo.article.service.IScenicService;
import cn.wolfcode.luowowo.article.service.IStrategyDetailService;
import cn.wolfcode.luowowo.article.service.ITravelService;
import cn.wolfcode.luowowo.cache.key.RedisTravelKey;
import cn.wolfcode.luowowo.cache.service.*;
import cn.wolfcode.luowowo.cache.vo.TravelStats;
import cn.wolfcode.luowowo.comment.domain.ScenicComment;
import cn.wolfcode.luowowo.comment.service.IScenicCommentService;
import cn.wolfcode.luowowo.common.query.TravelQuery;
import cn.wolfcode.luowowo.common.util.AjaxResult;
import cn.wolfcode.luowowo.common.util.Assert;
import cn.wolfcode.luowowo.common.util.Consts;
import cn.wolfcode.luowowo.member.domain.UserInfo;
import cn.wolfcode.luowowo.member.service.IUserInfoService;
import cn.wolfcode.luowowo.website.annotation.LoginUser;
import cn.wolfcode.luowowo.website.annotation.RequiredLogin;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 主页控制
 */
@Controller
@RequestMapping("/mine")
public class MineController {
    @Value("${file.dir}")
    private String fileDir;
    @Reference
    private ITravelService travelService;
    @Reference
    private ITravelStatsCacheService travelStatsCacheService;
    @Reference
    private IDestinationService destinationService;
    @Reference
    private IStrategyDetailService strategyDetailService;
    @Reference
    private IStrategyStatsCacheService strategyStatsCacheService;
    @Reference
    private IUserInfoService userInfoService;
    @Reference
    private ILoginInfoCacheService loginInfoCacheService;
    @Reference
    private IVerifyCodeCacheService verifyCodeCacheService;
    @Reference
    private IUserInfoCacheService userInfoCacheService;
    @Reference
    private IScenicCommentService scenicCommentService;
    @Reference
    private IScenicService scenicService;

    @RequestMapping("/home")
    @RequiredLogin
    public String home(@LoginUser UserInfo userInfo, Model model) {
        Long userId = userInfo.getId();
        //获取最早更新的前五篇游记
        model.addAttribute("travels", travelService.selectByAuthorId(userId));
        //获取这个用户所有的游记数
        model.addAttribute("travelCount", travelService.query4CountByAuthorId(userId));
        //获取用户的关注用户
        model.addAttribute("concerns", userInfoService.getConcernsUser(userId));
        //获取关注数
        model.addAttribute("userCount", userInfoService.getUserCount(userId));
        //获取被关注数
        model.addAttribute("beUserCount", userInfoService.getBeUserCount(userId));
        //获取前两个点评
        Set<Long> scenicsId = new HashSet<>();
        List<Scenic> scenics = new ArrayList<>();
        List<ScenicComment> scenicComments = scenicCommentService.findByUserId(userId);
        if (scenicComments != null) {
            for (ScenicComment scenicComment : scenicComments) {
                //去重
                scenicsId.add(scenicComment.getScenicId());
            }
            for (Long sId : scenicsId) {
                Scenic scenic = scenicService.selectByPrimaryKey(sId);
                scenics.add(scenic);
            }
        }
        //景点
        if (scenics.size() > 1) {
            model.addAttribute("scenics", scenics.subList(0, 2));
        } else {
            model.addAttribute("scenics", scenics);
        }
        //点评数
        model.addAttribute("scenicCount", scenicComments.size());
        return "/mine/homepage";
    }

    @RequestMapping("/thumbsup")
    @RequiredLogin
    @ResponseBody
    //游记点赞
    public Object thumbsup(Long id, @LoginUser UserInfo userInfo, Model model) {
        AjaxResult result = new AjaxResult();
        try {
            //1.调用服务进行点赞,返回结果
            boolean success = travelStatsCacheService.travelThumbup(id, userInfo.getId());
            //设置进result,共享给页面
            result.setSuccess(success);
            //2.更新统计数据
            //点赞成功
            if (success) {
                //点赞数加1
                travelStatsCacheService.addRank(RedisTravelKey.TRAVEL_STATS_HOT_SORT, 1, id);
            }
        } catch (Exception e) {
            e.printStackTrace();
            result.setCode(102);
        }
        //查询当前攻略的统计结果
        //查询当前攻略的统计结果
        TravelStats stats = travelStatsCacheService.get(id);
        return result.addData(stats.getThumbsupnum());
    }

    /**
     * 我的游记
     *
     * @param userInfo
     * @param model
     * @return
     */
    @RequestMapping("/travels")
    @RequiredLogin
    public String travels(@ModelAttribute("qo") TravelQuery qo, @LoginUser UserInfo userInfo, Model model) {
        Long userId = userInfo.getId();
        //1.查询游记--上传分页结果
        PageInfo pageInfo = travelService.queryByAuthorId(qo, userId);
        model.addAttribute("pageInfo", pageInfo);
        //3.游记总数
        int count = travelService.query4CountByAuthorId(userId);
        model.addAttribute("travelCount", count);
        //4.游记的回复总数
        model.addAttribute("replyCount", travelService.getReplyCountByAuthorId(userId));
        //5.游记的阅读总数
        model.addAttribute("viewCount", travelService.getViewCountByAuthorId(userId));
        //6.今日访问用户
        model.addAttribute("visitors", userInfoCacheService.getVisitor4Redis(userId));
        //7.获取今日统计数
        int todayRank = userInfoCacheService.getTodayRank(userId);
        model.addAttribute("todayRank", todayRank);
        //8.获取累计统计数
        int visitorsRank = userInfoCacheService.getVisitorsRank(userId);
        model.addAttribute("visitorsRank", visitorsRank);
        return "/mine/mytravelnotes";
    }

    /**
     * 我的收藏
     *
     * @param userInfo
     * @param model
     * @return
     */
    @RequestMapping("/collections")
    @RequiredLogin
    public String collections(@LoginUser UserInfo userInfo, Model model, String type) {
        Long userId = userInfo.getId();
        //进行目的地收藏显示
        model.addAttribute("dests", destinationService.getByUserId(userId));
        //进行游记收藏显示
        model.addAttribute("travels", travelService.getByUserId(userId));
        //进行攻略收藏显示
        model.addAttribute("strategys", strategyDetailService.getByUserId(userId));
        return "/mine/travelcollection";
    }

    /**
     * 攻略收藏取消
     *
     * @param userInfo
     * @param model
     * @return
     */
    @RequestMapping("/delStrategyCollection")
    @RequiredLogin
    @ResponseBody
    public Object delStrategyCollection(@LoginUser UserInfo userInfo, Model model, Long id) {
        AjaxResult result = new AjaxResult();
        Long userId = userInfo.getId();
        //1.删除mysql中的关系
        boolean sqlResult = strategyDetailService.deleteCollection(id);
        //2.删除redis中的收藏
        boolean rediResult = strategyStatsCacheService.deleteRedisCollection(id, userId);
        if (rediResult) {
            //3.修改redis的统计数
            strategyStatsCacheService.incr(id, -1, IStrategyStatsCacheService.FAVORNUM_TYPE);
        }
        if (!sqlResult && rediResult) {
            result.mark("删除收藏失败");
        }
        return result;
    }

    @RequestMapping("/delTravelCollection")
    @RequiredLogin
    @ResponseBody
    public Object delTravelCollection(@LoginUser UserInfo userInfo, Model model, Long id) {
        AjaxResult result = new AjaxResult();
        Long userId = userInfo.getId();
        //1.删除mysql中的关系
        boolean sqlResult = travelService.deleteCollection(id);
        if (!sqlResult) {
            result.mark("删除收藏失败");
        }
        return result;
    }

    /**
     * 个人设置
     *
     * @param userInfo
     * @param model
     * @return
     */
    @RequestMapping("/setting")
    @RequiredLogin
    public String setting(@LoginUser UserInfo userInfo, Model model) {
        model.addAttribute("gender", userInfo.getGender());
        model.addAttribute("blackList", userInfoService.getBlackList(userInfo.getId()));
        //页面跳转
        return "/mine/setting";
    }

    /**
     * 验证码
     *
     * @param code
     * @param phone
     * @return
     */
    @RequestMapping("/verifyCode")
    @RequiredLogin
    @ResponseBody
    public Object verifyCode(String code, String phone) {
        //验证手机和验证码
        AjaxResult result = userInfoService.checkPhoneAndverifyCode(code, phone);
        return result;
    }

    /**
     * 信息基本修改
     *
     * @param userInfo
     * @param request
     * @param session
     * @return
     */
    @RequestMapping("/settingUpdate")
    @RequiredLogin
    @ResponseBody
    public Object settingUpdate(UserInfo userInfo, HttpServletRequest request, HttpSession session) {
        AjaxResult result = new AjaxResult();
        try {
            //1.获取页面的cookie检查是否登录
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if (cookie.getName().equals(Consts.USER_INFO_TOKEN)) {
                        //获取token
                        String token = cookie.getValue();
                        //判断是否有未填入的信息
                        Assert.hasLength(userInfo.getNickname(), "请填入昵称");
                        Assert.hasLength(userInfo.getCity(), "请填入城市");
                        Assert.hasLength(userInfo.getInfo(), "请填入个人简介");
                        //1.修改用户的基本信息--返回完整的用户信息
                        UserInfo userBase = userInfoService.updateUserBase(userInfo);
                        //1.1修改redis的用户信息
                        loginInfoCacheService.setLoginInfo(token, JSON.toJSONString(userBase));
                        //1.2修改session中的登录信息
                        String loginInfo = loginInfoCacheService.getLoginInfo(token);
                        session.setAttribute(Consts.USER_INFO, JSON.parseObject(loginInfo, UserInfo.class));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            result.mark(e.getMessage());
        }
        return result;
    }

    /**
     * 头像修改
     *
     * @param userInfo
     * @param request
     * @param session
     * @return
     */
    @RequestMapping("/settingHeadUpdate")
    @RequiredLogin
    @ResponseBody
    public Object settingHeadUpdate(@LoginUser UserInfo userInfo, String headImgUrl, HttpServletRequest request, HttpSession session) {
        AjaxResult result = new AjaxResult();
        try {
            //1.获取页面的cookie检查是否登录
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if (cookie.getName().equals(Consts.USER_INFO_TOKEN)) {
                        //获取token
                        String token = cookie.getValue();
                        //1.修改用户的基本信息--返回完整的用户信息
                        UserInfo userHead = userInfoService.updateUserHead(userInfo, headImgUrl);
                        //1.1修改redis的用户信息
                        loginInfoCacheService.setLoginInfo(token, JSON.toJSONString(userHead));
                        //1.2修改session中的登录信息
                        String loginInfo = loginInfoCacheService.getLoginInfo(token);
                        session.setAttribute(Consts.USER_INFO, JSON.parseObject(loginInfo, UserInfo.class));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            result.mark(e.getMessage());
        }
        return result;
    }

    /**
     * 电话绑定修改
     *
     * @param userInfo
     * @param request
     * @param session
     * @return
     */
    @RequestMapping("/settingPhoneUpdate")
    @RequiredLogin
    @ResponseBody
    public Object settingPhoneUpdate(@LoginUser UserInfo userInfo, String phone, String code,
                                     HttpServletRequest request, HttpSession session) {
        AjaxResult result = new AjaxResult();
        try {
            //1.获取页面的cookie检查是否登录
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if (cookie.getName().equals(Consts.USER_INFO_TOKEN)) {
                        //获取token
                        String token = cookie.getValue();
                        //验证是否填入电话号码,验证码
                        Assert.hasLength(phone, "请填入电话号码");
                        Assert.hasLength(code, "请填验证码");
                        //验证码验证
                        String verifyCode4Redis = verifyCodeCacheService.getVerifyCode(phone);
                        Assert.equalsIgnoreCase(code, verifyCode4Redis, "验证码有误");
                        //1.修改用户的基本信息--返回完整的用户信息
                        UserInfo userHead = userInfoService.updateUserPhone(userInfo, phone);
                        //1.1修改redis的用户信息
                        loginInfoCacheService.setLoginInfo(token, JSON.toJSONString(userHead));
                        //1.2修改session中的登录信息
                        String loginInfo = loginInfoCacheService.getLoginInfo(token);
                        session.setAttribute(Consts.USER_INFO, JSON.parseObject(loginInfo, UserInfo.class));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            result.mark(e.getMessage());
        }
        return result;
    }

    /**
     * 我的点评
     *
     * @param userInfo
     * @param model
     * @return
     */
    @RequestMapping("/reviews")
    @RequiredLogin
    public String reviews(@LoginUser UserInfo userInfo, Model model) {
        Integer thumbupnum = 0;
        Set<Long> scenicsId = new HashSet<>();
        List<Scenic> scenics = new ArrayList<>();
        Long userId = userInfo.getId();
        List<ScenicComment> scenicComments = scenicCommentService.findByUserId(userId);
        if (scenicComments != null) {
            for (ScenicComment scenicComment : scenicComments) {
                //去重
                scenicsId.add(scenicComment.getScenicId());
                //点赞数
                thumbupnum += scenicComment.getThumbupnum();
            }
            for (Long sId : scenicsId) {
                Scenic scenic = scenicService.selectByPrimaryKey(sId);
                scenics.add(scenic);
            }
        }
        //1.景点
        model.addAttribute("scenics", scenics);
        //2.点评数
        model.addAttribute("commentCount", scenicComments.size());
        //3.点赞数
        model.addAttribute("thumbupnum", thumbupnum);
        //7.未点评
        Integer allSize = scenicService.selectAll().size();
        model.addAttribute("thumbupnumCount", allSize - scenicComments.size());
        return "/mine/review";
    }

    @RequestMapping("/concern")
    @RequiredLogin
    @ResponseBody
    public Object concern(Long beConcernId, @LoginUser UserInfo userInfo, Model model) {
        AjaxResult result = new AjaxResult();
        boolean success = true;
        try {
            //对传入的用户进行关注
            success = userInfoService.saveUserConcern(beConcernId, userInfo.getId());
        } catch (Exception e) {
            e.printStackTrace();
            result.setCode(102);
        }
        result.setSuccess(success);
        return result;
    }

    /**
     * 用户搜索
     *
     * @param name
     * @return
     */
    @RequestMapping("/searchUser")
    @RequiredLogin
    @ResponseBody
    public Object searchUser(@LoginUser UserInfo userInfo, String name) {
        AjaxResult result = new AjaxResult();
        try {
            Assert.hasLength(name, "请填入数据");
            UserInfo user = userInfoService.getUserByName(name);
            if (user.getId() == userInfo.getId()) {
                //查询的用户相同
                result.setSuccess(false);
                result.setMsg("不可查询自己");
            } else {
                result.addData(user);
            }
        } catch (Exception e) {
            e.printStackTrace();
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /**
     * 添加黑名单
     *
     * @param userInfo
     * @param blackId
     * @return
     */
    @RequestMapping("/blackUser")
    @RequiredLogin
    @ResponseBody
    public Object blackUser(@LoginUser UserInfo userInfo, Long blackId) {
        AjaxResult result = new AjaxResult();
        try {
            userInfoService.saveOrDeleteBlackList(userInfo.getId(), blackId);
        } catch (Exception e) {
            e.printStackTrace();
            result.setMsg(e.getMessage());
        }
        return result;
    }
}
